#include "tcp_perf_server.h"

#define TCP_SERVER_RX_BUFSIZE 2048
// static const u8 tcp_server_sendbuf[] = "Welcome to connect to the LWIP server.\r\n";

static void Demodulation_parameters_prase(unsigned long long value)
{
	switch (value & Acquisition_mode)
	{
	case Carrier_frequency_control_word:
		pDevicepara->carrierfrequencycw = value & 0xFFFFFFFFULL;
		pDevicepara->carrierfrequency = get_Carrierfreq_from_control_word(pDevicepara->carrierfrequencycw);
		SPI2_transfer64bit(Demodulation_parameters | Carrier_frequency_control_word | pDevicepara->carrierfrequencycw);
		break;
	case Symbol_rate_control_word:
		pDevicepara->symbolratecw = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Demodulation_parameters | Symbol_rate_control_word | pDevicepara->symbolratecw);
		break;
	case Modulation_system:
		pDevicepara->modulationsystem = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Demodulation_parameters | Modulation_system | pDevicepara->modulationsystem);
		break;
	case Spectrum_inversion:
		pDevicepara->spectruminversion = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Demodulation_parameters | Spectrum_inversion | pDevicepara->spectruminversion);
		break;
	case Symbol_rate_value:
		pDevicepara->symbolratevalue = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Demodulation_parameters | Symbol_rate_value | pDevicepara->symbolratevalue);
		break;
	case Balance:
		pDevicepara->balance = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Demodulation_parameters | Balance | pDevicepara->balance);
		break;
	default:
		printf("%s:errno value.\r\n", __FUNCTION__);
		break;
	}
}

static void Decoding_parameters_prase(unsigned long long value)
{
	switch (value & Acquisition_mode)
	{
	case Decoding_mode:
		pDevicepara->decodingmode = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Decoding_mode | pDevicepara->decodingmode);
		break;
	case Decoding_rate:
		pDevicepara->decodingrate = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Decoding_rate | pDevicepara->decodingrate);
		break;
	case RS_Decoding_mode:
		pDevicepara->RSdecodingmode = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | RS_Decoding_mode | pDevicepara->RSdecodingmode);
		break;
	case RS_Mixed_depth:
		pDevicepara->RSmixeddepth = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | RS_Mixed_depth | pDevicepara->RSmixeddepth);
		break;
	case Difference_options:
		pDevicepara->differenceoptions = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Difference_options | pDevicepara->differenceoptions);
		break;
	case Scrambler_format:
		pDevicepara->scramblerformat = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Scrambler_format | pDevicepara->scramblerformat);
		break;
	case Scrambler_initial_state:
		pDevicepara->scramblerinitialstate = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Scrambler_initial_state | pDevicepara->scramblerinitialstate);
		break;
	case Frame_structure:
		pDevicepara->framestructure = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(Decoding_parameters | Frame_structure | pDevicepara->framestructure);
		break;
	case Acquisition_mode:
		pDevicepara->acquisitionmode = value & 0xFFFFFFFFULL;
		SPI2_transfer64bit(OUTPUT | Acquisition_mode | pDevicepara->acquisitionmode);
		break;
	default:
		printf("%s:errno value.\r\n", __FUNCTION__);
		break;
	}
}

static void prase_data(char *data, int datalen)
{
	unsigned long long value = 0;
	int i = 0;
	if (datalen % 8 != 0)
	{
		printf("%s:data Mod 8 != 0.\r\n", __FUNCTION__);
	}
	for (i = 0; i < datalen / 8; i++)
	{
		memcpy(&value, data + i * 8, sizeof(unsigned long long));
		switch (value & OUTPUT)
		{
		case Demodulation_parameters:
			Demodulation_parameters_prase(value);
			break;
		case Decoding_parameters:
			Decoding_parameters_prase(value);
			break;
		default:
			printf("%s:errno value.\r\n", __FUNCTION__);
			break;
		}
	}
}

void tcp_new_client(void *arg)
{
	u32 data_len = 0;
	err_t recv_err, err;
	struct pbuf *q;
	struct netconn *newconn = (struct netconn *)arg;
	struct netbuf *recvbuf = NULL;
	u8 tcp_recvbuf[1024];
	OS_ERR os_err;
	u8 remot_addr[4];
	ip_addr_t ipaddr;
	u16_t port;
	printf("enter %s\r\n", __FUNCTION__);
	netconn_getaddr(newconn, &ipaddr, &port, 0);
	remot_addr[3] = (uint8_t)(ipaddr.addr >> 24);
	remot_addr[2] = (uint8_t)(ipaddr.addr >> 16);
	remot_addr[1] = (uint8_t)(ipaddr.addr >> 8);
	remot_addr[0] = (uint8_t)(ipaddr.addr);
	while (1)
	{
		// NSS_enable();
		// spi_trans_read(SPI_RX_BUFFER, SPI_TX_BUFFER, RX_LEN);
		// NSS_disable();
		err = netconn_write(newconn, /* tcp_server_sendbuf, strlen((char *)tcp_server_sendbuf) */ SPI_RX_BUFFER, RX_LEN, NETCONN_MORE);
		if (err != ERR_OK)
		{
			printf("send failed\r\n");
		}

		/* 接收消息 */
		recv_err = netconn_recv(newconn, &recvbuf);
		printf("%s:recv_err = %d\r\n", __FUNCTION__, recv_err);
		if (recv_err == ERR_OK && recvbuf->p != NULL)
		{
			if (data_len == 0)
			{
				memset(tcp_recvbuf, 0, TCP_SERVER_RX_BUFSIZE);
			}

			/* 将缓冲区信息转存到自定义空间 */
			for (q = recvbuf->p; q != NULL; q = q->next)
			{
				if (q->len > (TCP_SERVER_RX_BUFSIZE - data_len))
					memcpy(tcp_recvbuf + data_len, q->payload, (TCP_SERVER_RX_BUFSIZE - data_len));
				else
					memcpy(tcp_recvbuf + data_len, q->payload, q->len);
				data_len += q->len;
				if (data_len > TCP_SERVER_RX_BUFSIZE)
					break;
			}
			printf("%s\r\n", tcp_recvbuf);

			if (data_len > 8)
			{
				prase_data((char *)tcp_recvbuf, data_len);
				data_len = 0;
			}

			netbuf_delete(recvbuf);

			/* 断开连接 */
		}
		else //if (recv_err == ERR_CLSD)
		{
			printf("client:%d.%d.%d.%d disconnected\r\n", remot_addr[0], remot_addr[1], remot_addr[2], remot_addr[3]);
			netconn_close(newconn);
			netconn_delete(newconn);
			break;
		}
	}
	OSTaskDel((OS_TCB *)0, &os_err);
}

void start_application(void)
{
	err_t recv_err;
	u8 remot_addr[4];
	struct netconn *conn, *newconn;
	ip_addr_t ipaddr;
	u16_t port;
	conn = netconn_new(NETCONN_TCP);
	netconn_bind(conn, IP_ADDR_ANY, TCP_CONN_PORT);
	netconn_listen(conn);
	printf("%s:TCP server start.\r\n", __FUNCTION__);
	while (1)
	{
		recv_err = netconn_accept(conn, &newconn);
		if (recv_err == ERR_OK)
		{
			/* 获取到客户端的 IP 及端口号 */
			netconn_getaddr(newconn, &ipaddr, &port, 0);

			remot_addr[3] = (uint8_t)(ipaddr.addr >> 24);
			remot_addr[2] = (uint8_t)(ipaddr.addr >> 16);
			remot_addr[1] = (uint8_t)(ipaddr.addr >> 8);
			remot_addr[0] = (uint8_t)(ipaddr.addr);
			printf("client:%d.%d.%d.%d connected,port:%d\r\n", remot_addr[0], remot_addr[1], remot_addr[2], remot_addr[3], port);
			sys_thread_new("TCP_recv_perf thread",
						   tcp_new_client, (void *)newconn,
						   TCP_SERVER_THREAD_STACKSIZE,
						   DEFAULT_THREAD_PRIO);
		}
	}
}
